package com.qb9.flashlib.audio.player
{
	import com.qb9.flashlib.events.QEventDispatcher;
	import com.qb9.flashlib.tasks.ITask;
	import com.qb9.flashlib.tasks.TaskEvent;
	
	import flash.events.Event;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	
	public class AudioTask extends QEventDispatcher implements ITask
	{
		private var sound:Sound;
		private var channel:SoundChannel;
		private var transform:SoundTransform = new SoundTransform();
		private var lastPos:Number;
	
		public function AudioTask(sound:Sound, crop:Number=60)
		{
			this.sound = sound;
			lastPos = crop;
		}
	
		public function get running():Boolean
		{
			return channel !== null;
		}
	
		public function start():void
		{
			if (running)
				return;

			channel = sound.play(lastPos, 0, transform);
			channel.addEventListener(Event.SOUND_COMPLETE, onComplete);
		}
		
		public function stop():void
		{
			if (!running)
				return;

			lastPos = channel.position;
			channel.removeEventListener(Event.SOUND_COMPLETE, onComplete);
			channel.stop();
			channel = null;
		}
		
		public function get elapsed():uint
		{
			return running ? channel.position : lastPos;
		}
		
		// It's possible to advance the sound
		public function set elapsed(v:uint):void
		{
			var wasRunning:Boolean = running;
			stop();
			
			lastPos = v;
			if (wasRunning)
				start();
		}
		
		public function update(milliseconds:uint):void
		{
			// TODO: Maybe synchronize millis and sound?
		}
		
		public function get volume():Number
		{
			return transform.volume;
		}
		
		public function set volume(v:Number):void
		{
			transform.volume = v;
			if (channel)
				channel.soundTransform = transform;
		}
		
		public function get pan():Number
		{
			return transform.pan;
		}
		
		public function set pan(v:Number):void
		{
			transform.pan = v;
			if (channel)
				channel.soundTransform = transform;
		}
		
		private function onComplete(e:Event):void
		{
			dispatchEvent(new TaskEvent(TaskEvent.COMPLETE));
		}
	
		public function clone():ITask
		{
			var task:AudioTask = new AudioTask(sound);
			task.volume = volume;
			return task;
		}
		
		override public function dispose():void
		{
			stop();
			
			sound = null;
			transform = null;
			
			super.dispose();
		}
	}
}